// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

package types

import (
	"go/ast"
	"go/token"
)

// ----------------------------------------------------------------------------------------
// API 

// 接口表示接口类型。
type Interface struct {
	check     *Checker     // 用于错误报告；nil once类型集计算
	obj       *TypeName    // 定义此接口的类型名称对象；或者nil（更好的错误消息）
	methods   []*Func      // 显式声明方法的有序列表
	embeddeds []Type       // 显式嵌入元素的有序列表
	embedPos  *[]token.Pos // 嵌入元素的位置；或nil（对于错误消息）-使用指针来节省空间
	implicit  bool         // 接口是类型集文本的包装器（非接口T、~T或A | B）
	complete  bool         // 表示设置了obj、方法和嵌入，并且可以计算类型集

	tset *_TypeSet // 此接口描述的类型集，Lazy computed 
}

// typeSet返回接口t的类型集。
func (t *Interface) typeSet() *_TypeSet { return computeInterfaceTypeSet(t.check, token.NoPos, t) }

// emptyInterface表示空（已完成）接口
var emptyInterface = Interface{complete: true, tset: &topTypeSet}

// NewInterface返回给定方法和嵌入类型的新接口。
// NewInterface拥有提供的方法的所有权，并可以通过设置缺少的接收器来修改它们的类型
// 。
// 
// 已弃用：改用允许任意嵌入类型的NewInterfaceType。
func NewInterface(methods []*Func, embeddeds []*Named) *Interface {
	tnames := make([]Type, len(embeddeds))
	for i, t := range embeddeds {
		tnames[i] = t
	}
	return NewInterfaceType(methods, tnames)
}

// NewInterfaceType为给定的方法和嵌入的
// 类型返回一个新接口。NewInterfaceType拥有所提供方法的所有权，并且可以通过设置缺少的接收者来修改它们的类型。
// 
// 为了避免竞争条件，应该在
// 并发使用接口之前，通过显式调用Complete来计算接口的类型集。
func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface {
	if len(methods) == 0 && len(embeddeds) == 0 {
		return &emptyInterface
	}

	// 必要时设置方法接收器
	typ := (*Checker)(nil).newInterface()
	for _, m := range methods {
		if sig := m.typ.(*Signature); sig.recv == nil {
			sig.recv = NewVar(m.pos, m.pkg, "", typ)
		}
	}

	// 对API稳定性进行排序
	sortMethods(methods)

	typ.methods = methods
	typ.embeddeds = embeddeds
	typ.complete = true

	return typ
}

// 检查可能为零
func (check *Checker) newInterface() *Interface {
	typ := &Interface{check: check}
	if check != nil {
		check.needsCleanup(typ)
	}
	return typ
}

// 标记implicit将接口t标记为implicit，这意味着该接口
// 对应于一个约束文字，例如没有显式
// 接口嵌入的~t或a | B。在并发使用隐式接口之前，应先调用MarkImplicit。
func (t *Interface) MarkImplicit() {
	t.implicit = true
}

// NumExplicitMethods返回接口t显式声明的方法数。
func (t *Interface) NumExplicitMethods() int { return len(t.methods) }

// ExplicitMethod返回接口t的第i个显式声明的方法，其值为0<=i<t。NumExplicitMethods（）。
// 这些方法按其唯一Id排序。
func (t *Interface) ExplicitMethod(i int) *Func { return t.methods[i] }

// NumEmbeddeds返回接口t中嵌入类型的数量。
func (t *Interface) NumEmbeddeds() int { return len(t.embeddeds) }

// embedded返回接口t的第i个嵌入定义（*命名）类型（0<=i<t.NumEmbeddeds（）。
// 如果第i个嵌入类型不是已定义的类型，则结果为零。
// 
// 已弃用：使用EmbeddedType，它不限于已定义的（*命名）类型。
func (t *Interface) Embedded(i int) *Named { tname, _ := t.embeddeds[i].(*Named); return tname }

// EmbeddedType返回0<=i<t.numbeddeds（）的接口t的第i个嵌入类型。
func (t *Interface) EmbeddedType(i int) Type { return t.embeddeds[i] }

// NumMethods返回接口t的方法总数。
func (t *Interface) NumMethods() int { return t.typeSet().NumMethods() }

// Method返回0<=i<t.NumMethods（）的接口t的第i个方法。
// 这些方法按其唯一Id排序。
func (t *Interface) Method(i int) *Func { return t.typeSet().Method(i) }

// Empty报告t是否为空接口。
func (t *Interface) Empty() bool { return t.typeSet().IsAll() }

// IsCompable报告接口t的类型集中的每个类型是否具有可比性。
func (t *Interface) IsComparable() bool { return t.typeSet().IsComparable(nil) }

// IsMethodSet报告接口t是否用其方法
// set完整描述。
func (t *Interface) IsMethodSet() bool { return t.typeSet().IsMethodSet() }

// IsImplicit报告接口t是否是类型集文字的包装器。
func (t *Interface) IsImplicit() bool { return t.implicit }

// Complete计算接口的类型集。在接口的嵌入类型被完全定义之后，在以任何方式使用接口类型之前，
// NewInterfaceType和NewInterface的用户必须调用它，而不是以
// 形式使用其他类型。接口不能包含重复的方法或
// 出现死机。完成返回接收者。
// 
// 已完成的接口类型对于并发使用是安全的。
func (t *Interface) Complete() *Interface {
	if !t.complete {
		t.complete = true
	}
	t.typeSet() // 检查t.tset是否已设置nil 
	return t
}

func (t *Interface) Underlying() Type { return t }
func (t *Interface) String() string   { return TypeString(t, nil) }


func (t *Interface) cleanup() {
	t.check = nil
	t.embedPos = nil
}

func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, def *Named) {
	addEmbedded := func(pos token.Pos, typ Type) {
		ityp.embeddeds = append(ityp.embeddeds, typ)
		if ityp.embedPos == nil {
			ityp.embedPos = new([]token.Pos)
		}
		*ityp.embedPos = append(*ityp.embedPos, pos)
	}

	for _, f := range iface.Methods.List {
		if len(f.Names) == 0 {
			addEmbedded(f.Type.Pos(), parseUnion(check, f.Type))
			continue
		}

		// 我们有一个名为f.Names[0]的方法。
		name := f.Names[0]
		if name.Name == "_" {
			check.errorf(name, _BlankIfaceMethod, "invalid method name _")
			continue // 忽略
		}

		typ := check.typ(f.Type)
		sig, _ := typ.(*Signature)
		if sig == nil {
			if typ != Typ[Invalid] {
				check.invalidAST(f.Type, "%s is not a method signature", typ)
			}
			continue // 忽略
		}

		// 始终检查类型方法类型参数，但如果未启用，则会进行投诉。
		// /（此处需要额外检查，因为接口方法签名没有
		// 接收器规格。）
		if sig.tparams != nil {
			var at positioner = f.Type
			if ftyp, _ := f.Type.(*ast.FuncType); ftyp != nil && ftyp.TypeParams != nil {
				at = ftyp.TypeParams
			}
			check.errorf(at, _InvalidMethodTypeParams, "methods cannot have type parameters")
		}

		// 如果可用，请使用命名的接收器类型（为了获得更好的错误消息）
		var recvTyp Type = ityp
		if def != nil {
			recvTyp = def
		}
		sig.recv = NewVar(name.Pos(), check.pkg, "", recvTyp)

		m := NewFunc(name.Pos(), check.pkg, name.Name, sig)
		check.recordDef(name, m)
		ityp.methods = append(ityp.methods, m)
	}

	// 收集此接口的所有方法和嵌入元素；
	// 也就是说，这个接口可以用于类型集计算。
	ityp.complete = true

	if len(ityp.methods) == 0 && len(ityp.embeddeds) == 0 {
		// 空接口
		ityp.tset = &topTypeSet
		return
	}

	// 对API稳定性进行排序
	sortMethods(ityp.methods)
	// （不要对嵌入的进行排序：它们必须对应于*EmbeddedPos条目）

	// 尽快计算类型集以报告任何错误。
	// 类型集的后续使用将使用此计算类型
	// 集，并且不需要传入*检查器。
	check.later(func() {
		computeInterfaceTypeSet(check, iface.Pos(), ityp)
	}).describef(iface, "compute type set for %s", ityp)
}
